package com.pingan.haofang.searchcloud.web.index.controller;

import com.pingan.haofang.framework.common.functional.lang.control.bean.BeanCopy;
import com.pingan.haofang.searchcloud.common.constants.WebConstants;
import com.pingan.haofang.searchcloud.common.dto.OperationResult;
import com.pingan.haofang.searchcloud.common.dto.PageDTO;
import com.pingan.haofang.searchcloud.common.validator.annotation.Valid;
import com.pingan.haofang.searchcloud.index.constants.IndexBuildGradingType;
import com.pingan.haofang.searchcloud.index.constants.IndexBuildStatus;
import com.pingan.haofang.searchcloud.index.dto.IndexBuildProgressDTO;
import com.pingan.haofang.searchcloud.index.dto.IndexBuildProgressQuery;
import com.pingan.haofang.searchcloud.index.dto.IndexQueryResult;
import com.pingan.haofang.searchcloud.index.service.IndexBuildProgressService;
import com.pingan.haofang.searchcloud.index.service.IndexBuildService;
import com.pingan.haofang.searchcloud.index.service.IndexService;
import com.pingan.haofang.searchcloud.indexdatasource.dto.IndexDatasourceScheduleImportDTO;
import com.pingan.haofang.searchcloud.indexdatasource.facade.IndexDatasourceScheduleFacade;
import com.pingan.haofang.searchcloud.quartz.service.IndexBuildScheduleTaskService;
import com.pingan.haofang.searchcloud.user.dto.SearchProjectDto;
import com.pingan.haofang.searchcloud.user.service.SearchProjectService;
import com.pingan.haofang.searchcloud.web.index.form.IndexDatasourceScheduleImportForm;
import com.pingan.haofang.searchcloud.web.index.form.IndexIdForm;
import com.pingan.haofang.searchcloud.web.index.form.IndexScheduleForm;
import com.pingan.haofang.searchcloud.web.index.vo.IndexScheduleVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * 索引构建调度
 *
 * @author baojie371
 * @date 17/5/15
 * @since 1.0.0
 */
@RestController
@RequestMapping(value = WebConstants.WEB_PREFIX + "/datasource/schedule")
@Api(tags = "Index.Datasource.Schedule", description = "索引数据源接口")
public class IndexDatasourceScheduleController {

    private static final Logger LOGGER = LoggerFactory.getLogger(IndexDatasourceScheduleController.class);

    @Autowired
    private IndexDatasourceScheduleFacade indexDatasourceScheduleFacade;

    @Autowired
    private IndexBuildProgressService indexBuildProgressService;

    @Autowired
    private IndexService indexService;

    @Autowired
    private SearchProjectService searchProjectService;

    @Autowired
    private IndexBuildService indexBuildService;

    @Autowired
    private IndexBuildScheduleTaskService indexBuildScheduleTaskService;

    @RequestMapping(value = "/import/{indexId}", method = RequestMethod.PUT)
    @Valid
    @ApiOperation("执行导入")
    public OperationResult importDatasource(@ModelAttribute IndexIdForm indexIdForm,
                                            @RequestBody IndexDatasourceScheduleImportForm form) {
        IndexDatasourceScheduleImportDTO dto = BeanCopy.toFunction(IndexDatasourceScheduleImportDTO.class,
                BeanUtils::copyProperties).apply(form);
        return indexDatasourceScheduleFacade.importDatasource(indexIdForm.getIndexId(), dto);
    }

    @GetMapping(value = "")
    @ApiOperation("调度历史列表")
    @Valid
    public PageDTO<IndexScheduleVO> list(IndexScheduleForm form) {

        IndexBuildProgressQuery query = new IndexBuildProgressQuery();
        query.setBeginDate(form.getBeginDate());
        query.setEndDate(form.getEndDate());

        IndexQueryResult index = indexService.queryBasicInfoById(form.getIndexId());
        SearchProjectDto projectDto = searchProjectService.get(index.getProjectId());

        query.setProjectCode(projectDto.getProjectCode());
        query.setIndexName(index.getIndexName());
        query.setPageNo(form.getPageNo());
        query.setPageSize(form.getPageSize());
        if (form.getStatus() != null) {
            query.setStatus(form.getStatus());
        }


        LOGGER.info("query progrees:{}", query);
        PageDTO<IndexBuildProgressDTO> pageDTO = indexBuildProgressService.query(query);

        PageDTO<IndexScheduleVO> result = PageDTO.of(pageDTO, this::transferToVo);

        return result;
    }

    @GetMapping(value = "{id}")
    @ApiOperation("调度详情")
    public IndexScheduleVO get(@PathVariable(value = "id") Long id) {
        IndexBuildProgressDTO dto = indexBuildProgressService.query(id);
        return transferToVo(dto);
    }

    /**
     * 转换
     *
     * @param dto
     * @return
     */
    private IndexScheduleVO transferToVo(IndexBuildProgressDTO dto) {
        IndexScheduleVO vo = new IndexScheduleVO();
        vo.setId(dto.getId());
        vo.setRunType(dto.getRunType());
        vo.setIndexBuildType(dto.getIndexBuildType());
        vo.setStatus(dto.getStatus());
        vo.setStartTime(dto.getStartTime());
        vo.setExecuteStartTime(dto.getExecuteStartTime());
        vo.setExecuteEndTime(dto.getExecuteEndTime());
        vo.setExecuteCostTime(dto.getExecuteCostTime());
        vo.setCollectionName(dto.getCollectionName());
        vo.setFetchSuccessCount(dto.getFetchSuccessCount());
        vo.setFetchTotalCount(dto.getFetchTotalCount());
        vo.setImportSuccessCount(dto.getImportSuccessCount());
        vo.setImportTotalCount(dto.getImportTotalCount());
        vo.setConfigSnapshot(dto.getConfigSnapshot());
        vo.setFailReason(dto.getFailReason());
        vo.setDatasourceName(dto.getDatasourceName());

        // 如果返回数据源为空则是全索引
        if (StringUtils.isBlank(vo.getDatasourceName())) {
            vo.setGradingType(IndexBuildGradingType.INDEX.getValue());
        } else {
            vo.setGradingType(IndexBuildGradingType.DATABASE.getValue());
        }

        return vo;
    }

    /**
     * @Scheduled 调度任务刷新
     */
    @PutMapping(value = "refreshAll")
    @ApiOperation("调度任务刷新")
    public void refreshAll() throws SchedulerException {
        indexBuildScheduleTaskService.refreshAll();
    }

    /**
     * 中断任务
     *
     * @param id
     * @throws SchedulerException
     */
    @ApiOperation(value = "中断任务")
    @PutMapping(value = "/interrupt/{id}")
    public OperationResult interrupt(@PathVariable(value = "id") Long id) {
        IndexBuildProgressDTO indexBuildProgressDTO = indexBuildProgressService.query(id);

        boolean isLock = indexBuildService.checkLock(indexBuildProgressDTO.getProjectCode(), indexBuildProgressDTO.getIndexName());

        if(!isLock){
            indexBuildProgressDTO.setStatus(IndexBuildStatus.FAIL.value);
            indexBuildProgressService.updateProgress(indexBuildProgressDTO);
            return OperationResult.of(false, "该任务状态有误，请重新刷新页面状态！");
        }

        indexBuildScheduleTaskService.interrupt(id);
        return OperationResult.of(true, "即将中断任务！");
    }

    /**
     * 暂停任务
     *
     * @param progressId
     */
    @ApiOperation(value = "暂停任务")
    @PutMapping(value = "/pause/{progressId}")
    public OperationResult pause(@PathVariable(value = "progressId") Long progressId) {

        IndexBuildProgressDTO indexBuildProgressDTO = indexBuildProgressService.query(progressId);

        boolean isLock = indexBuildService.checkLock(indexBuildProgressDTO.getProjectCode(), indexBuildProgressDTO.getIndexName());

        if(!isLock){
            indexBuildProgressDTO.setStatus(IndexBuildStatus.FAIL.value);
            indexBuildProgressService.updateProgress(indexBuildProgressDTO);
            return OperationResult.of(false, "该任务状态有误，请重新刷新页面状态！");
        }

        return  indexBuildScheduleTaskService.pause(progressId);
    }

    /**
     * 继续任务
     *
     * @param progressId
     */
    @ApiOperation(value = "继续任务")
    @PutMapping(value = "/resume/{progressId}")
    public OperationResult resume(@PathVariable(value = "progressId") Long progressId) {
        return  indexBuildScheduleTaskService.resume(progressId);
    }

    /**
     * 放弃任务
     *
     * @param progressId
     */
    @ApiOperation(value = "放弃任务")
    @PutMapping(value = "/abort/{progressId}")
    public OperationResult abort(@PathVariable(value = "progressId") Long progressId) {
        return  indexBuildScheduleTaskService.abort(progressId);
    }

    /**
     * logurl
     *
     * @param progressId
     */
    @ApiOperation(value = "logurl")
    @GetMapping(value = "/getLogUrl/{progressId}")
    public String getLogUrl(@PathVariable(value = "progressId") Long progressId) {
        return  indexBuildScheduleTaskService.getLogUrl(progressId);
    }

}
